package org.tony.nio.demo;

import java.io.File;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

/**
 * 映射缓冲区。如果当前模式是PRIVATE的，那么其缓冲区数据的修改，是不会对文件数据照成修改的。
 * 
 * @author tangilin
 * 
 */
public class MappedFile
{

	public static void main(String[] args) throws Exception
	{
		File tempFile = File.createTempFile("test", null);
		RandomAccessFile raf = new RandomAccessFile(tempFile, "rw");
		FileChannel fc = raf.getChannel();

		ByteBuffer temp = ByteBuffer.allocate(100);
		temp.put("This is the testing for mapped file".getBytes());
		temp.flip();
		fc.write(temp);

		temp.clear();
		temp.put("This is more file Content".getBytes());
		temp.flip();
		fc.write(temp, 8192);

		MappedByteBuffer ro = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
		MappedByteBuffer rw = fc.map(FileChannel.MapMode.READ_WRITE, 0, fc.size());
		MappedByteBuffer prv = fc.map(FileChannel.MapMode.PRIVATE, 0, fc.size());

		System.out.println("<Begin>");
		showBuffers(ro, rw, prv);

		prv.position(8);
		prv.put(" <PRIVATE> ".getBytes());

		System.out.println("<prv Buffer has been changed>");
		showBuffers(ro, rw, prv);

		prv.position(8021);
		prv.put(" <PRIVATE2> ".getBytes());
		System.out.println("<prv Buffer second changed>");
		showBuffers(ro, rw, prv);

		rw.position(0);
		rw.put(" R/W2 ".getBytes());
		rw.position(8210);
		rw.put(" R/W2 ".getBytes());
		rw.force();
		System.out.println("Second change to R/W buffer");
		showBuffers(ro, rw, prv);

		fc.close();
		raf.close();
		tempFile.delete();
	}

	public static void showBuffers(ByteBuffer ro , ByteBuffer rw , ByteBuffer prv) throws Exception
	{
		dumpBuffer("R/O", ro);
		dumpBuffer("R/W", rw);
		dumpBuffer("PRV", prv);
		System.out.println("");
	}

	public static void dumpBuffer(String prefix , ByteBuffer buffer) throws Exception
	{

		System.out.print(prefix + ": '");
		int nulls = 0;
		int limit = buffer.limit();
		for (int i = 0; i < limit; i++)
		{
			char c = (char) buffer.get(i);
			if (c == '\u0000')
			{
				nulls++;
				continue;
			}
			if (nulls != 0)
			{
				System.out.print("|[" + nulls + " nulls]|");
				nulls = 0;
			}
			System.out.print(c);
		}
		System.out.println("'");
	}

}
